[Note] React: React.memo


Posted by urlun0404 on 2022-10-19

在了解React.memo的用途之前,複習一下React的幾個重要觀念:

  1. Component只會在state、props或context有更新的時候才會re-evaluate;
  2. Component re-evaluate的時候會連帶讓child components跟著 re-evaluate;
  3. 傳入child components的props無論有無改變都會跟著parent component一起re-evaluate;
  4. 如果child components還有自己的child component chain,則這些components也會跟著re-evaluate。


React.memo

當child component的sub-component tree非常龐大的,可以適當使用 React.memo 避免不必要的re-evaluate。

React.memo 會比較之前的props和parent component更新後的props有無不同,若相同則不會re-evaluate這個component,連帶也不會跟著re-evaluate的child components。

範例

Parent component

// App.js (parent component)
import {useState} from 'react';
import Me from './Me';
import Button from './Button';


export default function App(){
    console.log('App loads');

    const [isMe, setIsMe] = useState(false);

    const addMe = (event) => {
    event.preventDefault();
    setIsMe((prevMe) => !prevMe);
    };

    return (
        <>
            <h1>h1 always here</h1>
            <Me me={false}/>
            <Button onClick={addMe}>Click and Add Me!</Button>
        </>
    )
}


App component's child components

// Me.js (App's child component)
import React from "react";

function Me(props){
  console.log("Me loads");

  return <p>{props.isMe && `It's Me`}</p>;
}

export default React.memo(Me);
// Button.js (App's another child component)
import React from "react";

function Button(props){
    console.log('Button loads');

    return <button {...props}>{props.children}</button>;
}

export default React.memo(Button);

範例Me.js的 React.memo(Me) 這段會比較傳入props值(isMe)和前一次有無不同,範例內的isMe props刻意設為 false;由於每次都是傳入 false,所以 React.memo(Me) 這段會讓Me component在parent component更新的時候不會跟著更新:

要注意的是App.js每次re-render都會產生長得一模一樣卻儲存在不同位置的新 addMe 函式。

函式是物件,物件是屬於參考類型(reference type)變數,每次component更新時會產生一個和更新前內容相同、卻是儲存在不同位置的新物件。意思就是,每次component更新都會產生長得一模一樣的新函式,由於新函式和舊函式儲存在不同位址,同樣內容的物件儲存在不同位址就不會是同一個物件。

因此,每次更新產生的新函式就會是新的props並傳入Button component,才會讓Button.js檔案內的 React.memo() 沒有作用。



文章最後面會附上範例的live demo,可以觀察一下console;也可以fork回去,比較一下拿掉 React.memo 前後的Me component更新狀況有無不同。


References
React - The Complete Guide (incl Hooks, React Router, Redux)
Reference vs Primitive Values


Live Demo


#frontend #React #React.memo #memo #note







Related Posts

[27] 強制轉型 - 寬鬆相等 ( == ) vs. 嚴格相等 ( === )

[27] 強制轉型 - 寬鬆相等 ( == ) vs. 嚴格相等 ( === )

[JS101] JavaScript - 常用的內建函式

[JS101] JavaScript - 常用的內建函式

How to Install LAMP on Ubuntu 20.04

How to Install LAMP on Ubuntu 20.04


Comments